using System;
using System.Collections.Generic;
using System.Text;
using Jbe.TestSuite.TestDevice.Manager.Interface.Services;
using Jbe.TestSuite.Infrastructure.Interface;
using Microsoft.Practices.CompositeUI.EventBroker;
using Jbe.TestSuite.TestDevice.Manager.Constants;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.Commands;
using Microsoft.Practices.CompositeUI.Utility;

namespace Jbe.TestSuite.TestDevice.Manager.Services
{
    public class TestDeviceManager : ITestDeviceManager
    {
        [EventPublication(EventTopicNames.ControlViewsChanged, PublicationScope.WorkItem)]
        public event EventHandler<EventArgs<IList<IControlView>>> ControlViewsChanged;

        private WorkItem workItem;
        private Dictionary<string, IControlViewFactory> factories;
        private Dictionary<IDevice, IControlView> controlViews;
        private IList<IControlView> selectedControlViews;

        [ServiceDependency]
        public WorkItem WorkItem
        {
            set { workItem = value; }
        }

        public IList<IControlView> ControlViews
        {
            get { return new List<IControlView>(controlViews.Values).AsReadOnly(); }
        }

        public IList<IControlView> SelectedControlViews
        {
            get { return selectedControlViews; }
        }

        public TestDeviceManager()
        {
            factories = new Dictionary<string, IControlViewFactory>();
            controlViews = new Dictionary<IDevice, IControlView>();
            selectedControlViews = new List<IControlView>();
        }

        public void Register(IControlViewFactory factory)
        {
            Guard.ArgumentNotNull(factory, "factory");
            Guard.ArgumentNotNullOrEmptyString(factory.ProfileName, "factory.ProfileName");

            factories.Add(factory.ProfileName, factory);
        }

        public void Register(IDevice device)
        {
            Guard.ArgumentNotNull(device, "device");
            Guard.ArgumentNotNullOrEmptyString(device.ProfileName, "device.ProfileName");
            if (!factories.ContainsKey(device.ProfileName)) 
            { 
                throw new ArgumentException("No control view for the device profile '" + device.ProfileName + "' registered."); 
            }

            IControlView controlView = factories[device.ProfileName].Create(device.WorkItem);
            controlViews.Add(device, controlView);

            OnDevicesChanged(ControlViews);
        }

        public bool Deregister(IDevice device)
        {
            bool success = controlViews.Remove(device);
            OnDevicesChanged(ControlViews);
            return success;
        }

        protected virtual void OnDevicesChanged(IList<IControlView> devices) 
        {
            if (ControlViewsChanged != null) { ControlViewsChanged(this, new EventArgs<IList<IControlView>>(devices)); }
        }

        [CommandHandler(CommandNames.ShowDevice)]
        public void OpenDevice(object sender, EventArgs e)
        {
            foreach (IControlView controlView in selectedControlViews)
            {
                controlView.Show();
            }
        }

        [CommandHandler(CommandNames.CloseDevice)]
        public void RemoveDevice(object sender, EventArgs e)
        {
            foreach (IControlView controlView in selectedControlViews)
            {
                controlView.Close();
            }
        }

        [EventSubscription(EventTopicNames.SelectedControlViewsChanged)]
        public void SelectedControlViewsChanged(object sender, EventArgs<IList<IControlView>> e)
        {
            selectedControlViews = e.Data;
        }
    }
}
